package com.hube.platform.tenant.helper;

import com.hube.platform.tenant.entity.po.TenantDataBaseConfigPO;
import com.hube.platform.tenant.configuration.DynamicDataSource;
import com.hube.platform.tenant.constant.AppConstant;
import com.hube.platform.tenant.service.TenantInfoService;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import liquibase.exception.LiquibaseException;
import liquibase.integration.spring.SpringLiquibase;
import ma.glasnost.orika.MapperFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author : Aaron
 * @date : 2022/6/9
 */
@Component
public class LiquibaseRunner implements ApplicationRunner {

    private static final Logger log = LoggerFactory.getLogger(LiquibaseRunner.class);

    @Autowired
    private TenantInfoService tenantInfoService;

    @Resource(name = "tenantLiquibaseProperties")
    private LiquibaseProperties properties;

    private static final MapperFacade facade = FacadeBuilder.mapperFactory.getMapperFacade();

    @Override
    public void run(ApplicationArguments args) throws LiquibaseException {
        log.info("----开始同步租户数据库----");
        //获取所有租户数据源
        List<TenantDataBaseConfigPO> infoList = tenantInfoService.getBaseInfoList();
        init(infoList);
        log.info("----结束同步租户数据库----");
    }

    public void init(List<TenantDataBaseConfigPO> infoList) throws LiquibaseException {
        if (CollectionUtils.isEmpty(infoList)) {
            return;
        }
        List<HikariDataSource> datasourceList = new ArrayList<>();
        //注册liquibase
        for (TenantDataBaseConfigPO tenantConfig : infoList) {
            DynamicDataSource dynamicDataSource = (DynamicDataSource) ApplicationContextHelper.getBean(AppConstant.DYNAMIC_DATA_SOURCE);
            HikariDataSource dataSource = dynamicDataSource.addDataSource(tenantConfig.getTenantId(), tenantConfig.getDatabaseName(), facade.map(tenantConfig, HikariConfig.class));
            SpringLiquibase liquibase = ApplicationContextHelper.getBean(SpringLiquibase.class);
            liquibase.setDataSource(dataSource);
            liquibase.setChangeLog(properties.getChangeLog());
            liquibase.afterPropertiesSet();
            datasourceList.add(dataSource);
        }
        //关闭所有非主数据源
        datasourceList.forEach(item -> item.close());
        //处理 DataSource 对象
        DynamicDataSource dataSource = ApplicationContextHelper.getBean(DynamicDataSource.class);
        dataSource.clearDataSource();
        DynamicDataSourceContextHolder.clearCurrentDataSourceKey();
        DynamicDataSourceContextHolder.removeDateSourceKey();
    }
}
